# encoding: utf-8
from flask import Blueprint, views, render_template, make_response, request, redirect, url_for, session, g, abort
from io import BytesIO
from exts import db
from utils.captcha import Captcha
from utils import bbscache, restful, safe_utils
from apps.front.forms import SignupForm, SigninForm, AddPostForm, AddCommentForm, F_FoundPwdForm
from apps.front.models import FrontUser
from ..models import BannerModel, BoardModel, PostModel, CommentModel, HighlightPostModel, ReadpostModel
from .decorator import login_required
from flask_paginate import Pagination, get_page_parameter
import config
from datetime import datetime
from sqlalchemy.sql import func

bp = Blueprint('front', __name__)


@bp.route('/')
def index():
    board_id = request.args.get('bd', type=int, default=None)
    banners = BannerModel.query.order_by(BannerModel.priority.desc()).limit(4)
    boards = BoardModel.query.all()
    page = request.args.get(get_page_parameter(), type=int, default=1)
    start = (page - 1) * config.PER_PAGE
    end = start + config.PER_PAGE
    sort = request.args.get('st', type=int, default=1)
    query_obj = None
    if sort == 1:
        query_obj = PostModel.query.filter(PostModel.is_banned != 0).order_by(PostModel.create_time.desc())
    elif sort == 2:
        # 按照加精的时间倒叙排序
        query_obj = db.session.query(PostModel).outerjoin(HighlightPostModel).filter(PostModel.is_banned != 0).order_by(
            HighlightPostModel.create_time.desc(), PostModel.create_time.desc())
    elif sort == 3:
        query_obj = db.session.query(PostModel).outerjoin(ReadpostModel).filter(PostModel.is_banned != 0).group_by(
            PostModel.id).order_by(func.count(ReadpostModel.id).desc(), PostModel.create_time.desc())
    elif sort == 4:
        query_obj = db.session.query(PostModel).outerjoin(CommentModel).filter(PostModel.is_banned != 0).group_by(
            PostModel.id).order_by(func.count(CommentModel.id).desc(), PostModel.create_time.desc())

    if board_id:
        posts = query_obj.filter(PostModel.board_id == board_id).slice(start, end)
        total = query_obj.count()
    else:
        posts = query_obj.slice(start, end)
        total = query_obj.count()
    pagination = Pagination(bs_version=3, page=page, total=total)
    content = {
        'banners': banners,
        'boards': boards,
        'posts': posts,
        'pagination': pagination,
        'current_board': board_id,
        'current_sort': sort
    }
    return render_template('front/front_index.html', **content)


@bp.route('/search/')
def search():
    title = request.args.get('search')
    page = request.args.get(get_page_parameter(), type=int, default=1)
    start = (page - 1) * config.PER_PAGE
    end = start + config.PER_PAGE
    query_obj = PostModel.query.filter(PostModel.title.ilike('%{}%'.format(title)))
    posts = query_obj.order_by(PostModel.create_time.desc()).slice(start, end)
    total = query_obj.count()
    pagination = Pagination(bs_version=3, page=page, total=total)
    content = {
        'posts': posts,
        'pagination': pagination,
    }
    return render_template('front/front_search.html', **content)


@bp.route('/p/<post_id>')
def pdetail(post_id):
    post = PostModel.query.get(post_id)
    if not post:
        abort(404)
    if post.is_banned == 0:
        abort(404)
    else:
        if config.Front_USER_ID in session:
            # 查询这个帖子的阅读者
            reader = ReadpostModel.query.filter(
                ReadpostModel.post_id == post_id and ReadpostModel.author_id == g.front_user.id).order_by(
                ReadpostModel.id.desc()).first()
            if not reader:
                readpost = ReadpostModel()
                readpost.post = post
                readpost.author = g.front_user
                db.session.add(readpost)
                db.session.commit()
            else:
                now = datetime.now()
                timestramp = (now - reader.create_time).total_seconds()
                # 一分钟之内的多次点击只能算一次阅读
                if timestramp > 60:
                    readpost = ReadpostModel()
                    readpost.post = post
                    readpost.author = g.front_user
                    db.session.add(readpost)
                    db.session.commit()
        return render_template('front/front_pdetail.html', post=post)


@bp.route('/captcha/')
def graph_captcha():
    text, image = Captcha.gene_graph_captcha()
    # 字节流
    out = BytesIO()
    image.save(out, 'png')
    out.seek(0)
    resp = make_response(out.read())
    resp.content_type = 'image/png'
    bbscache.set(text.lower(), text.lower())
    return resp


@bp.route('/apost/', methods=['GET', 'POST'])
@login_required
def apost():
    if request.method == 'GET':
        boards = BoardModel.query.all()
        return render_template('front/front_apost.html', boards=boards)
    else:
        form = AddPostForm(request.form)
        if form.validate():
            title = form.title.data
            content = form.content.data
            board_id = form.board_id.data
            board = BoardModel.query.get(board_id)
            if not board:
                return restful.params_error(message='没有这个板块！')
            post = PostModel(title=title, content=content)
            post.board = board
            post.author = g.front_user
            try:
                db.session.add(post)
                db.session.commit()
                return restful.success()
            except Exception as e:
                print(e)
                return restful.params_error('发布出现异常！请稍后再试。')
        else:
            return restful.params_error(message=form.get_error())


@bp.route('/acomment/', methods=['GET', 'POST'])
def acomment():
    form = AddCommentForm(request.form)
    if form.validate():
        post_id = form.post_id.data
        content = form.content.data
        post = PostModel.query.get(post_id)
        if post:
            comment = CommentModel(content=content)
            comment.post = post
            comment.author = g.front_user
            db.session.add(comment)
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error('帖子不存在！')
    else:
        return restful.params_error(form.get_error())


class SignupView(views.MethodView):
    def get(self):
        return_to = request.referrer
        if return_to and return_to != request.url and safe_utils.is_safe_url((return_to)):
            return render_template('front/front_signup.html', return_to=return_to)
        else:
            return render_template('front/front_signup.html')

    def post(self):
        form = SignupForm(request.form)
        if form.validate():
            email = form.email.data
            username = form.username.data
            password = form.password1.data
            print(password)
            user = FrontUser(email=email, username=username, password=password)
            db.session.add(user)
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error(form.get_error())


class SigninView(views.MethodView):
    def get(self):
        return_to = request.referrer
        if return_to and return_to != request.url and return_to != url_for('front.signup') and safe_utils.is_safe_url(
                return_to):
            return render_template('front/front_signin.html', return_to=return_to)
        else:
            return render_template('front/front_signin.html')

    def post(self):
        form = SigninForm(request.form)
        if form.validate():
            email = form.email.data
            password = form.password.data
            remember = form.rememberPsw.data
            # print(telephone,password,remember)
            user = FrontUser.query.filter_by(email=email).first()
            if user and user.check_password(password):
                session[config.Front_USER_ID] = user.id
                if remember:
                    session.permanent = True
                print('登录成功！')
                return restful.success()
            else:
                return restful.params_error('邮箱或密码错误！')
        else:
            return restful.params_error(form.get_error())


bp.add_url_rule('/signup/', view_func=SignupView.as_view('signup'))
bp.add_url_rule('/signin/', view_func=SigninView.as_view('signin'))


# 前台用户找回密码
@bp.route('/fpwd/', methods=['GET', 'POST'])
def fpwd():
    if request.method == 'POST':
        form = F_FoundPwdForm(request.form)
        if form.validate():
            email = form.email.data
            password = form.password.data
            fuser = FrontUser.query.filter_by(email=email).first()
            if fuser:
                fuser.password = password
                db.session.commit()
                return restful.success()
            else:
                return restful.params_error('未查询到该用户的存在！')
        else:
            return restful.params_error(form.get_error())
    return render_template('front/front_signFpwd.html')


# 注销
@bp.route('/logout/')
@login_required
def logout():
    # session.clear()
    del session[config.Front_USER_ID]
    return redirect(url_for('front.index'))


@bp.app_template_filter('time_filter')
def time_filter(time):
    if isinstance(time, datetime):
        now = datetime.now()
        timestamp = (now - time).total_seconds()
        if timestamp < 60:
            return '刚刚'
        elif timestamp >= 60 and timestamp < 60 * 60:
            minutes = timestamp / 60
            return '%s分钟前' % int(minutes)
        elif timestamp >= 60 * 60 and timestamp < 60 * 60 * 24:
            hours = timestamp / (60 * 60)
            return '%s小时前' % int(hours)
        elif timestamp >= 60 * 60 * 24 and timestamp < 60 * 60 * 24 * 30:
            days = timestamp / (60 * 60 * 24)
            return '%s天前' % int(days)
        else:
            return time.strftime('%Y/%m/%d %H:%M')
    else:
        return time
